<?php

/**
 * Created by PhpStorm.
 * User: Administrator
 * Date: 2019/5/27
 * Time: 15:27
 */

namespace PKFrame\Driver;
defined('PATH_PK') or die();

use PKFrame\DataHandler\Arrays;

class Sqlite
{
    private $_path;

    public function __construct($path)
    {
        try {
            if (!extension_loaded('sqlite3')) {
                throw new \Exception(language('PHPExtension_Sqlite_NoExists'));
            }
            $this->_path = $path;
        } catch (\Exception $e) {
            $this->_notice($e);
        }
    }

    private function _notice(\Exception $exception)
    {
        out()->noticeByJson($exception->getMessage());
    }

    private function _conn(): \SQLite3
    {
        try {
            if (!file_exists($this->_path)) {
                throw new \Exception(language('DataBase_SqliteFile_NoExists') . $path);
            }
        } catch (\Exception $exception) {
            $this->_notice($exception);
        }
        return new \SQLite3($this->_path);
    }

    private function _errorLog(\SQLite3 $conn, $sqlStr)
    {
        logger()->LOGS($conn->lastErrorMsg(), array('sql' => $sqlStr, 'ErrorCode' => $conn->lastErrorCode()));
    }

    public function sqlQuery($sqlStr)
    {
        !empty($sqlStr) ?: out()->noticeByJson('do sql is empty');
        try {
            $conn = $this->_conn();
            $conn->busyTimeout(10);
            $conn->exec($sqlStr);
            if ($conn->lastErrorCode() != 0) {
                $this->_errorLog($conn, $sqlStr);
                throw new \Exception(language('DataBase_Sql_NumError'));
            }
            $conn->close();
        } catch (\Exception $exception) {
            $this->_notice($exception);
        }
    }

    public function fetchAssoc($sqlStr, $toList = false)
    {
        !empty($sqlStr) ?: out()->noticeByJson('do sql is empty');
        $result = [];
        try {
            $conn = $this->_conn();
            if ($toList) {
                $sth = $conn->query($sqlStr);
                if ($conn->lastErrorCode() != 0) {
                    $this->_errorLog($conn, $sqlStr);
                    throw new \Exception(language('DataBase_Sql_NumError'));
                }
                while ($row = $sth->fetchArray(SQLITE3_ASSOC)) {
                    array_push($result, $row);
                    //                    $result[] = $row;
                }
            } else {
                $result = $conn->querySingle($sqlStr, TRUE);
                if ($conn->lastErrorCode() != 0) {
                    $this->_errorLog($conn, $sqlStr);
                    throw new \Exception(language('DataBase_Sql_NumError'));
                }
            }
        } catch (\Exception $exception) {
            $this->_notice($exception);
        }
        return $result;
    }

    public function insert($sqlStr)
    {
        !empty($sqlStr) ?: out()->noticeByJson('do sql is empty');
        try {
            $conn = $this->_conn();
            if (Arrays::Is($sqlStr)) {
                $conn->exec(implode(';', $sqlStr));
            }
            if ($conn->lastErrorCode() != 0) {
                $this->_errorLog($conn, $sqlStr);
                throw new \Exception(language('DataBase_Sql_NumError'));
            }
            $conn->close();
        } catch (\Exception $exception) {
            $this->_notice($exception);
        }
    }

    public function insertId($sqlStr)
    {
        !empty($sqlStr) ?: out()->noticeByJson('do sql is empty');
        try {
            $conn = $this->_conn();
            $conn->busyTimeout(10);
            $conn->exec($sqlStr);
            if ($conn->lastErrorCode() != 0) {
                $this->_errorLog($conn, $sqlStr);
                throw new \Exception(language('DataBase_Sql_NumError'));
            }
            $id = $conn->lastInsertRowID();
            $conn->close();
            return $id;
        } catch (\Exception $exception) {
            $this->_notice($exception);
        }
    }

    public function __destruct()
    {
        $this->_conn()->close();
    }
}
